# -*- coding: utf-8 -*-
"""
主题管理器
用于管理和初始化所有主题下的Python文件
"""
import os
import sys
import importlib.util
from typing import Dict, List, Any, Optional


class ThemeManager:
    """主题管理器类"""
    
    def __init__(self, app=None):
        self.app = app
        self.themes = {}
        self.initialized_modules = {}
        self.templates_path = None
        
    def set_app(self, app):
        """设置Flask应用实例"""
        self.app = app
        
    def get_templates_path(self) -> str:
        """获取templates目录的绝对路径"""
        if self.templates_path is None:
            project_root = os.path.dirname(os.path.dirname(os.path.dirname(os.path.abspath(__file__))))
            self.templates_path = os.path.join(project_root, 'apps', 'modules', 'main', 'templates')
        return self.templates_path
        
    def discover_themes(self) -> Dict[str, str]:
        """发现所有主题目录"""
        templates_path = self.get_templates_path()
        
        if not os.path.exists(templates_path):
            print(f"❌ templates目录不存在: {templates_path}")
            return {}
            
        themes = {}
        for item in os.listdir(templates_path):
            item_path = os.path.join(templates_path, item)
            if os.path.isdir(item_path):
                themes[item] = item_path
                print(f"🔍 发现主题: {item}")
                
        return themes
        
    def load_python_file(self, file_path: str, module_name: str) -> Optional[Any]:
        """动态加载Python文件"""
        try:
            if not os.path.exists(file_path):
                return None
                
            spec = importlib.util.spec_from_file_location(module_name, file_path)
            module = importlib.util.module_from_spec(spec)
            spec.loader.exec_module(module)
            return module
            
        except Exception as e:
            print(f"❌ 加载模块 {module_name} 失败: {e}")
            return None
            
    def init_theme_functions(self, theme_name: str, theme_path: str) -> bool:
        """初始化主题的functions.py文件"""
        functions_path = os.path.join(theme_path, 'functions.py')
        
        if not os.path.exists(functions_path):
            print(f"ℹ️ {theme_name} 主题下没有functions.py文件")
            return False
            
        try:
            print(f"🔍 发现functions.py在: {theme_name}")
            
            module_name = f"functions_{theme_name}"
            functions_module = self.load_python_file(functions_path, module_name)
            
            if functions_module is None:
                return False
                
            if hasattr(functions_module, 'init'):
                if self.app:
                    functions_module.init(self.app)
                else:
                    functions_module.init()
                print(f"✅ {theme_name} 主题functions模块初始化成功")
                self.initialized_modules[f"{theme_name}_functions"] = functions_module
                return True
            else:
                print(f"⚠️ {theme_name} 主题functions模块没有init函数")
                self.initialized_modules[f"{theme_name}_functions"] = functions_module
                return True
                
        except Exception as e:
            print(f"❌ 初始化 {theme_name} 主题functions模块时发生错误: {e}")
            import traceback
            traceback.print_exc()
            return False
            
    def init_theme_config(self, theme_name: str, theme_path: str) -> bool:
        """初始化主题的config.py文件"""
        config_path = os.path.join(theme_path, 'config.py')
        
        if not os.path.exists(config_path):
            print(f"ℹ️ {theme_name} 主题下没有config.py文件")
            return False
            
        try:
            print(f"🔍 发现config.py在: {theme_name}")
            
            module_name = f"config_{theme_name}"
            config_module = self.load_python_file(config_path, module_name)
            
            if config_module is None:
                return False
                
            if hasattr(config_module, 'init'):
                if self.app:
                    config_module.init(self.app)
                else:
                    config_module.init()
                print(f"✅ {theme_name} 主题config模块初始化成功")
                self.initialized_modules[f"{theme_name}_config"] = config_module
                return True
            else:
                print(f"⚠️ {theme_name} 主题config模块没有init函数")
                self.initialized_modules[f"{theme_name}_config"] = config_module
                return True
                
        except Exception as e:
            print(f"❌ 初始化 {theme_name} 主题config模块时发生错误: {e}")
            import traceback
            traceback.print_exc()
            return False
            
    def init_theme_view(self, theme_name: str, theme_path: str) -> bool:
        """初始化主题的view.py文件（蓝图）"""
        view_path = os.path.join(theme_path, 'view.py')
        
        if not os.path.exists(view_path):
            print(f"ℹ️ {theme_name} 主题下没有view.py文件")
            return False
            
        try:
            print(f"🔍 发现view.py在: {theme_name}")
            
            module_name = f"view_{theme_name}"
            view_module = self.load_python_file(view_path, module_name)
            
            if view_module is None:
                return False
                
            # 查找蓝图对象
            blueprint = None
            for attr_name in dir(view_module):
                attr = getattr(view_module, attr_name)
                if hasattr(attr, 'name') and hasattr(attr, 'url_prefix'):
                    # 这很可能是一个Flask蓝图
                    blueprint = attr
                    break
            
            if blueprint is None:
                print(f"⚠️ {theme_name} 主题view.py中没有找到蓝图对象")
                self.initialized_modules[f"{theme_name}_view"] = view_module
                return False
                
            # 如果找到了蓝图，注册到Flask应用
            if self.app:
                try:
                    # 检查蓝图是否已经注册
                    if blueprint.name not in self.app.blueprints:
                        # 检查应用是否已经处理过请求
                        if hasattr(self.app, '_got_first_request') and self.app._got_first_request:
                            print(f"⚠️ Flask应用已处理过请求，无法注册蓝图 {blueprint.name}")
                            print(f"ℹ️ 蓝图 {blueprint.name} 将在下次应用重启时自动注册")
                            # 将蓝图存储在待注册列表中，供后续使用
                            if not hasattr(self, '_pending_blueprints'):
                                self._pending_blueprints = {}
                            self._pending_blueprints[blueprint.name] = blueprint
                        else:
                            self.app.register_blueprint(blueprint)
                            print(f"✅ {theme_name} 主题蓝图注册成功: {blueprint.name}")
                    else:
                        print(f"ℹ️ {theme_name} 主题蓝图已存在: {blueprint.name}")
                except Exception as e:
                    print(f"❌ 注册 {theme_name} 主题蓝图失败: {e}")
                    # 如果是运行时注册失败，将蓝图存储在待注册列表中
                    if not hasattr(self, '_pending_blueprints'):
                        self._pending_blueprints = {}
                    self._pending_blueprints[blueprint.name] = blueprint
                    print(f"ℹ️ 蓝图 {blueprint.name} 已添加到待注册列表")
            else:
                print(f"⚠️ Flask应用未设置，无法注册 {theme_name} 主题蓝图")
                
            # 如果view模块有init函数，则调用它
            if hasattr(view_module, 'init'):
                if self.app:
                    view_module.init(self.app)
                else:
                    view_module.init()
                print(f"✅ {theme_name} 主题view模块初始化成功")
                
            self.initialized_modules[f"{theme_name}_view"] = view_module
            self.initialized_modules[f"{theme_name}_blueprint"] = blueprint
            return True
                
        except Exception as e:
            print(f"❌ 初始化 {theme_name} 主题view模块时发生错误: {e}")
            import traceback
            traceback.print_exc()
            return False
            
    def init_theme(self, theme_name: str, theme_path: str) -> bool:
        """初始化单个主题的所有Python文件"""
        print(f"\n🚀 开始初始化主题: {theme_name}")
        
        success_count = 0
        total_count = 0
        
        # 初始化functions.py
        if self.init_theme_functions(theme_name, theme_path):
            success_count += 1
        total_count += 1
        
        # 初始化config.py
        if self.init_theme_config(theme_name, theme_path):
            success_count += 1
        total_count += 1
        
        # 初始化view.py（蓝图）
        if self.init_theme_view(theme_name, theme_path):
            success_count += 1
        total_count += 1
        
        print(f"📊 {theme_name} 主题初始化完成: {success_count}/{total_count} 个模块成功")
        return success_count > 0
        
    def init_all_themes(self) -> Dict[str, bool]:
        """初始化所有主题"""
        print("🎯 开始初始化所有主题...")
        
        self.themes = self.discover_themes()
        
        if not self.themes:
            print("⚠️ 没有发现任何主题")
            return {}
            
        results = {}
        total_success = 0
        
        for theme_name, theme_path in self.themes.items():
            success = self.init_theme(theme_name, theme_path)
            results[theme_name] = success
            if success:
                total_success += 1
                
        print(f"\n🎉 主题初始化完成: {total_success}/{len(self.themes)} 个主题成功")
        return results
        
    def get_initialized_modules(self) -> Dict[str, Any]:
        """获取所有已初始化的模块"""
        return self.initialized_modules
        
    def get_module(self, module_name: str) -> Optional[Any]:
        """获取指定的模块"""
        return self.initialized_modules.get(module_name)
        
    def unload_theme(self, theme_name: str) -> bool:
        """
        卸载指定主题的所有模块
        
        Args:
            theme_name: 主题名称
            
        Returns:
            bool: 卸载是否成功
        """
        if theme_name not in self.themes:
            print(f"❌ 主题 {theme_name} 不存在或未初始化")
            return False
            
        print(f"🔄 开始卸载主题: {theme_name}")
        
        # 需要卸载的模块类型
        module_types = ['functions', 'config', 'helpers', 'utils', 'view']
        unloaded_count = 0
        
        for module_type in module_types:
            module_key = f"{theme_name}_{module_type}"
            if module_key in self.initialized_modules:
                try:
                    # 如果模块有unload函数，则调用它
                    module = self.initialized_modules[module_key]
                    if hasattr(module, 'unload'):
                        if self.app:
                            module.unload(self.app)
                        else:
                            module.unload()
                        print(f"✅ {theme_name} 主题 {module_type} 模块卸载成功")
                    else:
                        print(f"ℹ️ {theme_name} 主题 {module_type} 模块没有unload函数")
                    
                    # 从已初始化模块中移除
                    del self.initialized_modules[module_key]
                    unloaded_count += 1
                    
                    # 如果是view模块，还需要注销蓝图
                    if module_type == 'view' and self.app:
                        blueprint_key = f"{theme_name}_blueprint"
                        if blueprint_key in self.initialized_modules:
                            blueprint = self.initialized_modules[blueprint_key]
                            try:
                                # 注销蓝图
                                if blueprint.name in self.app.blueprints:
                                    del self.app.blueprints[blueprint.name]
                                    print(f"✅ {theme_name} 主题蓝图已注销: {blueprint.name}")
                                del self.initialized_modules[blueprint_key]
                            except Exception as e:
                                print(f"❌ 注销 {theme_name} 主题蓝图时发生错误: {e}")
                    
                except Exception as e:
                    print(f"❌ 卸载 {theme_name} 主题 {module_type} 模块时发生错误: {e}")
                    import traceback
                    traceback.print_exc()
        
        # 从主题列表中移除
        if theme_name in self.themes:
            del self.themes[theme_name]
            print(f"📊 {theme_name} 主题已从主题列表中移除")
        
        print(f"🎉 {theme_name} 主题卸载完成: {unloaded_count} 个模块已卸载")
        return unloaded_count > 0
        
    def unload_all_themes(self) -> Dict[str, bool]:
        """
        卸载所有主题
        
        Returns:
            Dict[str, bool]: 主题名称到卸载结果的映射
        """
        print("🔄 开始卸载所有主题...")
        
        if not self.themes:
            print("ℹ️ 没有已初始化的主题需要卸载")
            return {}
            
        results = {}
        total_success = 0
        
        # 获取所有主题名称的副本，因为卸载过程中会修改self.themes
        theme_names = list(self.themes.keys())
        
        for theme_name in theme_names:
            success = self.unload_theme(theme_name)
            results[theme_name] = success
            if success:
                total_success += 1
                
        print(f"\n🎉 主题卸载完成: {total_success}/{len(theme_names)} 个主题成功卸载")
        return results
        
    def reload_theme(self, theme_name: str) -> bool:
        """
        重新加载指定主题
        
        Args:
            theme_name: 主题名称
            
        Returns:
            bool: 重新加载是否成功
        """
        print(f"🔄 开始重新加载主题: {theme_name}")
        
        # 先卸载主题
        unload_success = self.unload_theme(theme_name)
        
        # 重新发现主题
        self.themes = self.discover_themes()
        
        # 重新初始化主题
        if theme_name in self.themes:
            theme_path = self.themes[theme_name]
            init_success = self.init_theme(theme_name, theme_path)
            
            if init_success:
                print(f"✅ {theme_name} 主题重新加载成功")
                return True
            else:
                print(f"❌ {theme_name} 主题重新加载失败")
                return False
        else:
            print(f"❌ 重新发现主题时未找到 {theme_name}")
            return False
            
    def get_theme_status(self, theme_name: str) -> Dict[str, Any]:
        """
        获取指定主题的状态信息
        
        Args:
            theme_name: 主题名称
            
        Returns:
            Dict[str, Any]: 主题状态信息
        """
        status = {
            'name': theme_name,
            'exists': theme_name in self.themes,
            'path': self.themes.get(theme_name, ''),
            'modules': {},
            'total_modules': 0,
            'loaded_modules': 0
        }
        
        if theme_name in self.themes:
            # 检查各种模块类型
            module_types = ['functions', 'config', 'helpers', 'utils', 'view']
            
            for module_type in module_types:
                module_key = f"{theme_name}_{module_type}"
                module = self.initialized_modules.get(module_key)
                
                status['modules'][module_type] = {
                    'loaded': module is not None,
                    'has_init': hasattr(module, 'init') if module else False,
                    'has_unload': hasattr(module, 'unload') if module else False
                }
                
                if module:
                    status['loaded_modules'] += 1
                    
                status['total_modules'] += 1
                
        return status
        
    def get_all_themes_status(self) -> Dict[str, Dict[str, Any]]:
        """
        获取所有主题的状态信息
        
        Returns:
            Dict[str, Dict[str, Any]]: 所有主题的状态信息
        """
        status = {}
        
        for theme_name in self.themes.keys():
            status[theme_name] = self.get_theme_status(theme_name)
            
        return status
        
    def enable_theme(self, theme_name: str) -> bool:
        """
        启用指定主题
        
        Args:
            theme_name: 主题名称
            
        Returns:
            bool: 启用是否成功
        """
        print(f"🚀 开始启用主题: {theme_name}")
        
        # 检查主题是否存在
        if theme_name not in self.themes:
            print(f"❌ 主题 {theme_name} 不存在，尝试重新发现...")
            # 重新发现主题
            self.themes = self.discover_themes()
            
            if theme_name not in self.themes:
                print(f"❌ 主题 {theme_name} 不存在于templates目录中")
                return False
        
        # 检查主题是否已经启用（已初始化）
        theme_path = self.themes[theme_name]
        theme_status = self.get_theme_status(theme_name)
        
        if theme_status['loaded_modules'] > 0:
            print(f"ℹ️ 主题 {theme_name} 已经启用")
            return True
        
        # 初始化主题
        print(f"🔄 初始化主题 {theme_name}...")
        success = self.init_theme(theme_name, theme_path)
        
        if success:
            print(f"✅ 主题 {theme_name} 启用成功")
            
            # 检查是否有待注册的蓝图，如果有则创建重载配置文件
            pending_blueprints = getattr(self, '_pending_blueprints', {})
            if pending_blueprints:
                self._create_reload_config()
            
            return True
        else:
            print(f"❌ 主题 {theme_name} 启用失败")
            return False
            
    def disable_theme(self, theme_name: str) -> bool:
        """
        禁用指定主题（卸载但不从主题列表中移除）
        
        Args:
            theme_name: 主题名称
            
        Returns:
            bool: 禁用是否成功
        """
        print(f"🔄 开始禁用主题: {theme_name}")
        
        if theme_name not in self.themes:
            print(f"❌ 主题 {theme_name} 不存在")
            return False
        
        # 检查主题是否已经禁用
        theme_status = self.get_theme_status(theme_name)
        
        if theme_status['loaded_modules'] == 0:
            print(f"ℹ️ 主题 {theme_name} 已经禁用")
            return True
        
        # 卸载主题的所有模块
        module_types = ['functions', 'config', 'helpers', 'utils', 'view']
        unloaded_count = 0
        
        for module_type in module_types:
            module_key = f"{theme_name}_{module_type}"
            if module_key in self.initialized_modules:
                try:
                    # 如果模块有unload函数，则调用它
                    module = self.initialized_modules[module_key]
                    if hasattr(module, 'unload'):
                        if self.app:
                            module.unload(self.app)
                        else:
                            module.unload()
                        print(f"✅ {theme_name} 主题 {module_type} 模块卸载成功")
                    else:
                        print(f"ℹ️ {theme_name} 主题 {module_type} 模块没有unload函数")
                    
                    # 从已初始化模块中移除
                    del self.initialized_modules[module_key]
                    unloaded_count += 1
                    
                    # 如果是view模块，还需要注销蓝图
                    if module_type == 'view' and self.app:
                        blueprint_key = f"{theme_name}_blueprint"
                        if blueprint_key in self.initialized_modules:
                            blueprint = self.initialized_modules[blueprint_key]
                            try:
                                # 注销蓝图
                                if blueprint.name in self.app.blueprints:
                                    del self.app.blueprints[blueprint.name]
                                    print(f"✅ {theme_name} 主题蓝图已注销: {blueprint.name}")
                                del self.initialized_modules[blueprint_key]
                            except Exception as e:
                                print(f"❌ 注销 {theme_name} 主题蓝图时发生错误: {e}")
                    
                except Exception as e:
                    print(f"❌ 卸载 {theme_name} 主题 {module_type} 模块时发生错误: {e}")
                    import traceback
                    traceback.print_exc()
        
        print(f"🎉 主题 {theme_name} 禁用完成: {unloaded_count} 个模块已卸载")
        return unloaded_count > 0
        
    def switch_theme(self, from_theme: str, to_theme: str) -> bool:
        """
        切换主题（从当前主题切换到新主题）
        
        Args:
            from_theme: 当前主题名称
            to_theme: 目标主题名称
            
        Returns:
            bool: 切换是否成功
        """
        print(f"🔄 开始切换主题: {from_theme} -> {to_theme}")
        
        # 禁用当前主题
        if from_theme and from_theme in self.themes:
            disable_success = self.disable_theme(from_theme)
            if not disable_success:
                print(f"⚠️ 禁用主题 {from_theme} 时出现问题，但继续切换")
        
        # 启用目标主题
        enable_success = self.enable_theme(to_theme)
        
        if enable_success:
            print(f"✅ 主题切换成功: {from_theme} -> {to_theme}")
            return True
        else:
            print(f"❌ 主题切换失败: {from_theme} -> {to_theme}")
            return False
            
    def get_active_theme(self) -> Optional[str]:
        """
        获取当前激活的主题
        
        Returns:
            str: 激活的主题名称，如果没有则返回None
        """
        active_themes = []
        
        for theme_name in self.themes.keys():
            theme_status = self.get_theme_status(theme_name)
            if theme_status['loaded_modules'] > 0:
                active_themes.append(theme_name)
        
        if len(active_themes) == 1:
            return active_themes[0]
        elif len(active_themes) > 1:
            print(f"⚠️ 发现多个激活主题: {active_themes}")
            return active_themes[0]  # 返回第一个
        else:
            return None
            
    def list_available_themes(self) -> List[str]:
        """
        列出所有可用的主题
        
        Returns:
            List[str]: 可用主题名称列表
        """
        # 重新发现主题
        self.themes = self.discover_themes()
        return list(self.themes.keys())
        
    def list_active_themes(self) -> List[str]:
        """
        列出所有激活的主题
        
        Returns:
            List[str]: 激活主题名称列表
        """
        active_themes = []
        
        for theme_name in self.themes.keys():
            theme_status = self.get_theme_status(theme_name)
            if theme_status['loaded_modules'] > 0:
                active_themes.append(theme_name)
        
        return active_themes
        
    def get_pending_blueprints(self) -> Dict[str, Any]:
        """
        获取待注册的蓝图列表
        
        Returns:
            Dict[str, Any]: 待注册的蓝图字典
        """
        return getattr(self, '_pending_blueprints', {})
        
    def register_pending_blueprints(self) -> bool:
        """
        注册所有待注册的蓝图
        
        Returns:
            bool: 注册是否成功
        """
        if not self.app:
            print("❌ Flask应用未设置，无法注册待注册的蓝图")
            return False
            
        pending_blueprints = getattr(self, '_pending_blueprints', {})
        if not pending_blueprints:
            print("ℹ️ 没有待注册的蓝图")
            return True
            
        print(f"🔄 开始注册 {len(pending_blueprints)} 个待注册的蓝图...")
        success_count = 0
        
        for blueprint_name, blueprint in pending_blueprints.items():
            try:
                if blueprint_name not in self.app.blueprints:
                    self.app.register_blueprint(blueprint)
                    print(f"✅ 蓝图 {blueprint_name} 注册成功")
                    success_count += 1
                else:
                    print(f"ℹ️ 蓝图 {blueprint_name} 已存在")
                    success_count += 1
            except Exception as e:
                print(f"❌ 注册蓝图 {blueprint_name} 失败: {e}")
                
        # 清空待注册列表
        self._pending_blueprints = {}
        
        print(f"🎉 蓝图注册完成: {success_count}/{len(pending_blueprints)} 个成功")
        return success_count == len(pending_blueprints)
        
    def get_blueprint_status(self) -> Dict[str, Any]:
        """
        获取蓝图状态信息
        
        Returns:
            Dict[str, Any]: 蓝图状态信息
        """
        status = {
            'registered_blueprints': [],
            'pending_blueprints': [],
            'total_blueprints': 0
        }
        
        if self.app:
            status['registered_blueprints'] = list(self.app.blueprints.keys())
            
        pending_blueprints = getattr(self, '_pending_blueprints', {})
        status['pending_blueprints'] = list(pending_blueprints.keys())
        status['total_blueprints'] = len(status['registered_blueprints']) + len(status['pending_blueprints'])
        
        return status
        
    def _create_reload_config(self):
        """
        创建重载配置文件
        """
        try:
            import os
            import json
            import time
            
            print("🔄 检测到待注册的蓝图，创建重载配置文件...")
            
            # 获取待注册的蓝图信息
            pending_blueprints = getattr(self, '_pending_blueprints', {})
            pending_info = {}
            
            # 保存蓝图详细信息
            for name, blueprint in pending_blueprints.items():
                pending_info[name] = {
                    'name': blueprint.name,
                    'url_prefix': blueprint.url_prefix,
                    'template_folder': blueprint.template_folder,
                    'static_folder': getattr(blueprint, 'static_folder', None),
                    'static_url_path': getattr(blueprint, 'static_url_path', None)
                }
            
            # 创建重载配置文件
            reload_config = {
                'timestamp': time.time(),
                'pending_blueprints': list(pending_blueprints.keys()),
                'pending_blueprint_info': pending_info,
                'action': 'reload_app',
                'reason': 'pending_blueprints_detected'
            }
            
            # 获取项目根目录
            project_root = os.path.dirname(os.path.dirname(os.path.dirname(os.path.abspath(__file__))))
            reload_file = os.path.join(project_root, 'reload_app.json')
            
            # 写入重载配置
            with open(reload_file, 'w', encoding='utf-8') as f:
                json.dump(reload_config, f, indent=2, ensure_ascii=False)
            
            print(f"✅ 重载配置文件已创建: {reload_file}")
            print("ℹ️ 请使用 auto_reload_monitor.py 监控此文件以自动重启应用")
            
        except Exception as e:
            print(f"❌ 创建重载配置文件失败: {e}")


# 全局主题管理器实例
theme_manager = ThemeManager()


def init_theme_manager(app=None):
    """初始化主题管理器"""
    if app:
        theme_manager.set_app(app)
    
    theme_manager.init_all_themes()
    return theme_manager


def get_theme_manager() -> ThemeManager:
    """获取主题管理器实例"""
    return theme_manager


# 测试
if __name__ == '__main__':
    init_theme_manager() 